﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;

namespace SpaceEngine.Assets
{
    public class Quad : DrawableGameComponent
    {
        Game1 game;
        Texture2D texture;
        BasicEffect effect;
        VertexBuffer vertices;
        IndexBuffer indices;
        VertexDeclaration vertexDecl;
        Vector2 size;
        protected Vector3 position;
        protected Vector3 rotation;
        protected String texturePath;

        public Quad(Game1 game, Vector3 pos, Vector3 rot, String tex, Vector2 size)
            : base(game)
        {
            this.game = game;
            this.size = size;
            texturePath = tex;
            position = pos;
            rotation = rot;
        }

        public override void Initialize()
        {
            base.Initialize();

            texture = game.manager.Load<Texture2D>(texturePath);
            effect = new BasicEffect(game.graphics.GraphicsDevice, null);

            // vertex declaration required by renderer
            // contains two elements: Position(v3) and TextureCoordinate(v2)
            vertexDecl = new VertexDeclaration(game.graphics.GraphicsDevice,
                new VertexElement[]
                {
                    new VertexElement(0,0,VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Position,0),
                    new VertexElement(0,sizeof(float)*3,VertexElementFormat.Vector2,VertexElementMethod.Default,VertexElementUsage.TextureCoordinate,0)
                });

            // create a vertex buffer with 4 vertices per star
            vertices = new VertexBuffer(game.graphics.GraphicsDevice, typeof(VertexPositionTexture), 4, BufferUsage.WriteOnly);

            // create an index buffer with 6 indices per star
            indices = new IndexBuffer(game.graphics.GraphicsDevice, typeof(short), 6, BufferUsage.WriteOnly);

            // create 4 vertices with texture info
            VertexPositionTexture[] data = new VertexPositionTexture[4];
            data[0].Position = new Vector3(position.X - size.X / 2, position.Y, position.Z - size.Y / 2);
            data[0].TextureCoordinate.X = 1.0f;
            data[0].TextureCoordinate.Y = 1.0f;
            data[1].Position = new Vector3(position.X - size.X / 2, position.Y, position.Z + size.Y / 2);
            data[1].TextureCoordinate.X = 1.0f;
            data[1].TextureCoordinate.Y = 0.0f;
            data[2].Position = new Vector3(position.X + size.X / 2, position.Y, position.Z + size.Y / 2);
            data[2].TextureCoordinate.X = 0.0f;
            data[2].TextureCoordinate.Y = 0.0f;
            data[3].Position = new Vector3(position.X + size.X / 2, position.Y, position.Z - size.Y / 2);
            data[3].TextureCoordinate.X = 0.0f;
            data[3].TextureCoordinate.Y = 1.0f;

            // add indices
            short[] ib = new short[6];
            ib[0] = (short)(0);
            ib[1] = (short)(2);
            ib[2] = (short)(1);
            ib[3] = (short)(2);
            ib[4] = (short)(0);
            ib[5] = (short)(3);

            vertices.SetData<VertexPositionTexture>(data);
            indices.SetData<short>(ib);
            
        }

        public override void Update(GameTime gameTime)
        {

            effect.World =                 
                Matrix.CreateRotationX(rotation.X) * 
                Matrix.CreateRotationY(rotation.Y) * 
                Matrix.CreateRotationZ(rotation.Z) *
                Matrix.CreateTranslation(position);
            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            // nothing to draw
            if (vertices == null)
                return;

            // set up effect params
            
            effect.View = game.camera.View;
            effect.Projection = game.camera.Projection;
            effect.LightingEnabled = false;
            effect.TextureEnabled = true;

            // begin effects, set up graphics device
            effect.Begin();
            game.graphics.GraphicsDevice.VertexDeclaration = vertexDecl;
            game.graphics.GraphicsDevice.Vertices[0].SetSource(vertices, 0, vertexDecl.GetVertexStrideSize(0));
            game.graphics.GraphicsDevice.Indices = indices;
            game.graphics.GraphicsDevice.RenderState.PointSpriteEnable = true;
            game.graphics.GraphicsDevice.RenderState.SourceBlend = Blend.SourceAlpha;
            game.graphics.GraphicsDevice.RenderState.DestinationBlend = Blend.SourceAlpha;
            game.graphics.GraphicsDevice.RenderState.AlphaBlendEnable = true;
            effect.Texture = texture;

            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Begin();
                game.graphics.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, 4, 0, 2);
                pass.End();
            }
            effect.End();


            // reset render settings
            game.graphics.GraphicsDevice.RenderState.AlphaBlendEnable = false;
            
            base.Draw(gameTime);
        }

        public Vector3 Position
        {
            get { return position; }
            set { position = value; }
        }

        public Vector3 Rotation
        {
            get { return rotation; }
            set { rotation = value; }
        }

    }
}
